package handler

import (
	"encoding/binary"
	"encoding/json"
	"errors"
	"fmt"
	"gin_maker_chat/client/utils"
	"gin_maker_chat/model"
	"net"
)

type UserHandler struct {
}

func (this *UserHandler) Register(userCode, userName, userNick, passWord string) (err error) {
	sip := "127.0.0.1"
	port := 8888

	//链接server
	conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", sip, port))

	if err != nil {
		fmt.Println("net.Dial error:", err)
		return nil
	}
	//延时关闭
	defer conn.Close()
	//准备通过conn发送消息给服务端
	var msg model.Message
	msg.Type = model.ResisterMsgType
	//注册
	var registerMsg model.RegisterMsg
	registerMsg.User.UserCode = userCode
	registerMsg.User.UserName = userName
	registerMsg.User.NickName = userNick
	registerMsg.User.PassWord = passWord
	//将loginMsg序列化
	data, err := json.Marshal(registerMsg)
	if err != nil {
		fmt.Println("registerMsg json.Marshal error=", err)
		return
	}
	//将data传送给msg.Data
	msg.Data = string(data)

	//将msg序列化
	data, err = json.Marshal(msg)

	if err != nil {
		fmt.Println("registerMsg msg json.Marshal error=", err)
		return
	}
	transfer := &utils.Transfer{
		Conn: conn,
	}
	transfer.WriteMsgByNetCon(data)
	if err != nil {
		fmt.Println("注册发送消息 error=", err)
		return
	}

	msg, err = transfer.ReadMsgByNetCon()
	if err != nil {
		fmt.Println("register  read msg fail ,error=", err)
		return
	}
	var registerResMsg model.RegisterResMsg
	err = json.Unmarshal([]byte(msg.Data), &registerResMsg)
	if err != nil {
		fmt.Println("registerRes read msg json.Unmarshal ,error=", err)
		return
	}

	if registerResMsg.Code == 200 {
		//登录成功后，需要在客户端启动一个协程
		//该协程目的保持和服务器端的通讯，如果服务器有数据推送给客户端
		//接收并显示在客户端
		// go process.KeepConnectClientAndServer(conn)
		fmt.Println("注册成功")
	} else {
		fmt.Println("注册失败,err", registerResMsg.Code, registerResMsg.Error)
		return errors.New(registerResMsg.Error)
	}

	return

}

func (this *UserHandler) Login(userName, passWord string) (err error) {

	sip := "127.0.0.1"
	port := 8888

	//链接server
	conn, err := net.Dial("tcp", fmt.Sprintf("%s:%d", sip, port))

	if err != nil {
		fmt.Println("net.Dial error:", err)
		return nil
	}
	//延时关闭
	defer conn.Close()

	//准备通过conn发送消息给服务端
	var msg model.Message
	msg.Type = model.LoginMsgType
	//登录
	var loginMsg model.LoginMsg
	loginMsg.UserName = userName
	loginMsg.PassWord = passWord
	//将loginMsg序列化
	data, err := json.Marshal(loginMsg)
	if err != nil {
		fmt.Println("loginMsg json.Marshal error=", err)
		return
	}
	//将data传送给msg.Data
	msg.Data = string(data)

	//将msg序列化
	data, err = json.Marshal(msg)

	if err != nil {
		fmt.Println("loginMsg msg json.Marshal error=", err)
		return
	}

	//将data发送到服务器
	//2.1 先将data的长度发送服务器
	//获取data的长度 -> 转成一个表示长度的byte切片
	pkgLen := uint32(len(data))
	var buf = make([]byte, 4)
	binary.BigEndian.PutUint32(buf[0:4], pkgLen)
	//发送长度
	n, err := conn.Write(buf)
	if n != 4 || err != nil {
		fmt.Println(" client sent to len fail ,error=", err)
		return
	}
	fmt.Printf("客户端发送长度=%d  内容=%s", len(data), string(data))

	//发送消息
	_, err = conn.Write(data)
	if err != nil {
		fmt.Println(" client sent to msg fail ,error=", err)
		return
	}

	//接收服务器返回的消息
	//休息20s
	// time.Sleep(20 * time.Second)
	// fmt.Println("休息20s")
	transfer := &utils.Transfer{
		Conn: conn,
	}

	msg, err = transfer.ReadMsgByNetCon()
	if err != nil {
		fmt.Println(" read msg fail ,error=", err)
		return
	}
	var loginResMsg model.LoginResMsg
	err = json.Unmarshal([]byte(msg.Data), &loginResMsg)
	if err != nil {
		fmt.Println(" read msg json.Unmarshal ,error=", err)
		return
	}
	if loginResMsg.Code == 200 {
		//显示当前在线用户列表
		for _, username := range loginResMsg.UserNames {
			//如果不显示当前用户的在线信息，可以过滤掉
			if username == userName {
				continue
			}
			fmt.Println("用户名:\t", username)
			//完成客户端对onlineUsers的初始化
			user := &model.User{
				UserName:   username,
				UserStatus: model.UserOnline,
			}
			fmt.Println("客户端对onlineUsers的初始化，新上线用户：", user)
			UserMgr.OnlineUsers[username] = user
		}

		//登录成功后，需要在客户端启动一个协程
		//该协程目的保持和服务器端的通讯，如果服务器有数据推送给客户端
		//接收并显示在客户端
		go KeepConnectClientAndServer(conn)
		fmt.Println("登录成功")
		return
	} else {
		fmt.Println("login code,err", loginResMsg.Code, loginResMsg.Error)
		return errors.New(loginResMsg.Error)
	}
}
